/*
 * TDA_SVN.h
 *
 *  Created on: Oct 4, 2013
 *      Author: enano
 */


#include "TDA_TAV.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>

#define INICIO 0
#define VACIO 0
#define MINIMO 1
#define CSTR_FIN 1
#define NOT !
#define EQUAL 0
#define ARCH_UNO 0
#define ARCH_DOS 1

#define CSTR_LONG 100
#define FECHA_LONG 18
#define COMENT_LONG 10
#define EXT_TAV_LONG 4
#define EXT_REV_LONG 2
#define EXT_CUR_LONG 8
#define COMENT_VACIO_LONG 1

#define INSE "I@"
#define ELIM "E@"
#define EXTENSION_TAV ".tav"
#define EXTENSION_CURRENT ".current"
#define COMENT_VACIO "\0"

/* Errores */
#define ERR_MALLOC -4

typedef int tDupla[2];


int gettime (char* strFechaHora, size_t *longStr)
{
    time_t fechaHora;
    struct tm* tm_info;

    time(&fechaHora);
    tm_info = localtime(&fechaHora);

    *longStr = strftime(strFechaHora, FECHA_LONG, "%Y-%m-%d %H:%M", tm_info);
    if ( longStr == VACIO ) return ERROR;

    (*longStr)++;

    return OK;
}


int consultarTAV (const TAV *tav, modo_uso_t modo, int *contenido)
{   size_t tavNombreLong, rutaLong;
    char *tavNombre;
    FILE *archTAV;

    rutaLong = strlen(tav->ruta)+CSTR_FIN;
    tavNombreLong = rutaLong + EXT_TAV_LONG + CSTR_FIN;
    tavNombre = (char*) malloc ( tavNombreLong * sizeof(char) );
    if ( tavNombre == NULL ) return ERR_MALLOC;

    strncpy( tavNombre, tav->ruta, rutaLong );
    strncat( tavNombre, EXTENSION_TAV, EXT_TAV_LONG );

    if ( modo == TAV_CREAR )
    {
        archTAV = fopen(tavNombre, "w+");
        *contenido = INICIO;
        free(tavNombre);
        if ( archTAV == NULL ) return ERR_ABRIR_ARCHIVO;
        fprintf(archTAV, "%d", *contenido);
    }
    else /* modo == TAV_USAR */
    {
        archTAV = fopen(tavNombre, "r+");
        free(tavNombre);
        if ( archTAV == NULL ) return ERR_ABRIR_ARCHIVO;
        fscanf(archTAV, "%d", contenido);
    }

    fclose(archTAV);

    return OK;
}


int borrarTAV ( const TAV *tav )
{   size_t tavNombreLong, rutaLong;
    char *tavNombre;
    int result;

    rutaLong = strlen(tav->ruta)+CSTR_FIN;
    tavNombreLong = rutaLong + EXT_TAV_LONG + CSTR_FIN;
    tavNombre = (char*) malloc ( tavNombreLong * sizeof(char) );
    if ( tavNombre == NULL ) return ERR_MALLOC;

    strncpy( tavNombre, tav->ruta, rutaLong );
    strncat( tavNombre, EXTENSION_TAV, EXT_TAV_LONG );

    result = remove(tavNombre);
    free(tavNombre);
    if ( result != OK ) return ERROR;

    return OK;
}


int verificarCURRENT(const TAV *tav, modo_uso_t modo)
{   size_t curNombreLong, rutaLong;
    char* curNombre;
    FILE *archCUR;

    rutaLong = strlen(tav->ruta)+CSTR_FIN;
    curNombreLong = rutaLong + EXT_CUR_LONG + CSTR_FIN;
    curNombre = (char*) malloc ( curNombreLong * sizeof(char) );
    if ( curNombre == NULL ) return ERR_MALLOC;

    strncpy( curNombre, tav->ruta, rutaLong );
    strncat( curNombre, EXTENSION_CURRENT, EXT_CUR_LONG );

    if ( modo == TAV_CREAR )
    {
        archCUR = fopen(curNombre,"a");
    }
    else /* modo == TAV_USAR */
    {
        archCUR = fopen(curNombre,"r+");
    }

    free(curNombre);
    if ( archCUR == NULL ) return ERR_ABRIR_ARCHIVO;
    fclose(archCUR);

    return OK;
}


int actualizarCURRENT(TAV *tav)
{   size_t curNombreLong, rutaLong;
    char *curNombre, linea[CSTR_LONG];
    FILE *arch, *archCUR;

    rutaLong = strlen(tav->ruta)+CSTR_FIN;
    curNombreLong = rutaLong + EXT_CUR_LONG + CSTR_FIN;
    curNombre = (char*) malloc ( curNombreLong * sizeof(char) );
    if ( curNombre == NULL ) return ERR_MALLOC;

    strncpy( curNombre, tav->ruta, rutaLong );
    strncat( curNombre, EXTENSION_CURRENT, EXT_CUR_LONG );

    arch = fopen(tav->ruta,"r+");       /* Abre el arch original (nuevo) para leerlo. */
    archCUR = fopen(curNombre, "w+");   /* Abre el CURRENT, a sobreescribir. */
    free(curNombre);

    if ( archCUR == NULL ) return ERR_ABRIR_ARCHIVO;
    if ( arch == NULL ) return ERR_ABRIR_ARCHIVO;

    while ( fgets(linea, CSTR_LONG, arch) != NULL )
    {
        /* fscanf(arch, "%[^\n]s", linea); */
        /* fgets(linea, CSTR_LONG, arch); */
        fprintf(archCUR, "%s", linea);
    }

    fclose(arch);
    fclose(archCUR);

    return OK;
}


int abrirCURRENT (const TAV *tav, FILE **archCUR)
{   size_t curNombreLong, rutaLong;
    char* curNombre;

    rutaLong = strlen(tav->ruta)+CSTR_FIN;
    curNombreLong = rutaLong + EXT_CUR_LONG + CSTR_FIN;
    curNombre = (char*) malloc ( curNombreLong * sizeof(char) );
    if ( curNombre == NULL ) return ERR_MALLOC;

    strncpy( curNombre, tav->ruta, rutaLong );
    strncat( curNombre, EXTENSION_CURRENT, EXT_CUR_LONG );

    *archCUR = fopen(curNombre,"r+");
    free(curNombre);
    if ( *archCUR == NULL ) return ERR_ABRIR_ARCHIVO;

    return OK;

}


int borrarCURRENT ( const TAV *tav )
{   size_t curNombreLong, rutaLong;
    char* curNombre;
    int result;

    rutaLong = strlen(tav->ruta)+CSTR_FIN;
    curNombreLong = rutaLong + EXT_CUR_LONG + CSTR_FIN;
    curNombre = (char*) malloc ( curNombreLong * sizeof(char) );
    if ( curNombre == NULL ) return ERR_MALLOC;

    strncpy( curNombre, tav->ruta, rutaLong );
    strncat( curNombre, EXTENSION_CURRENT, EXT_CUR_LONG );

    result = remove(curNombre);
    free(curNombre);
    if ( result != OK ) return ERROR;

    return OK;
}


int insertarFinalLista (TListaSimple *lista, revision_t *dato)
{
    while ( L_Mover_Cte(lista, L_Siguiente) == TRUE )
    {
        /* Recorre la lista sin hacer nada, asegurandose
         * de quedar en la última posisicón por si se
         * modificó el corriente previamente.
         * */
    }

    L_Insertar_Cte(lista, L_Siguiente, dato);

    return OK;
}


int actualizarTAV(TAV *tav, info_revision_t info, const TCola *cambios)
{   revision_t revision;

    revision.info = info;
    revision.cambios = *cambios;

    /* insertarFinalLista( &(tav->revisiones), &revision ); */
    L_Insertar_Cte( &(tav->revisiones), L_Siguiente, &revision);


    return OK;
}


int actualizarArchTAV( TAV *tav )
{   size_t tavNombreLong, rutaLong;
    char *tavNombre;
    FILE *archTAV;
    int version;

    rutaLong = strlen(tav->ruta)+CSTR_FIN;
    tavNombreLong = rutaLong + EXT_TAV_LONG + CSTR_FIN;
    tavNombre = (char*) malloc ( tavNombreLong * sizeof(char) );
    if ( tavNombre == NULL ) return ERR_MALLOC;

    strncpy( tavNombre, tav->ruta, rutaLong );
    strncat( tavNombre, EXTENSION_TAV, EXT_TAV_LONG );

    archTAV = fopen(tavNombre, "r+");
    free(tavNombre);
    if ( archTAV == NULL ) return ERR_ABRIR_ARCHIVO;

    fscanf(archTAV, "%d", &version);
    rewind(archTAV);
    /* if ( version == INICIO ) version++; */
    version++;
    fprintf(archTAV, "%d", version);
    fclose(archTAV);

    return OK;
}


int abrirVersionN(const TAV *tav, int numVersion, FILE **arch)
{   size_t verNombreLong, rutaLong;
    char* verNombre;
    char verExt[3];
    int verExtLong;

    rutaLong = strlen(tav->ruta)+CSTR_FIN;
    verNombreLong = rutaLong + EXT_REV_LONG + CSTR_FIN;
    verNombre = (char*) malloc ( verNombreLong * sizeof(char) );
    if ( verNombre == NULL ) return ERR_MALLOC;

    strncpy(verNombre, tav->ruta, rutaLong);
    verExtLong = sprintf(verExt, ".%d", numVersion);
    strncat(verNombre, verExt, verExtLong);

    *arch = fopen(verNombre,"r+");
    free(verNombre);
    if ( *arch == NULL ) return ERR_ABRIR_ARCHIVO;

    return OK;
}

int revcpy (revision_t *dest, revision_t *src)
{
    /* TODO tengo que copiar la revision de forma
     * que no este pasando la memoria allocada en
     * Heap original, perteneciente al TAV
     */

    return OK;
}


int encontrarRevision(TAV *tav, int version, revision_t *rev )
{   /* revision_t revAux; */
    /* TODO Revisar, cuando copio la 'rev' le paso la original
     * y después la estoy liberando en escribirRevision
     * por eso el error cuando libero en TAV_CERRAR */

    L_Elem_Cte( tav->revisiones, rev);  /* &revAux */
    while ( rev->info.num != version )  /* revAux.info.num  */
    {
        if ( rev->info.num > version )  /* revAux.info.num  */
            L_Mover_Cte( &(tav->revisiones), L_Anterior);
        else
            L_Mover_Cte( &(tav->revisiones), L_Siguiente);

        L_Elem_Cte(tav->revisiones, rev);  /* &revAux */
    }

    return OK;
}


int escribirRevision( revision_t *rev, FILE **arch)
{   cambio_t cambios;

    fprintf(*arch, "Revision: %d\n", rev->info.num );
    fprintf(*arch, "%s\n", rev->info.fecha);
    fprintf(*arch, "Comentario: %s\n", rev->info.comentario);
    /* fprintf(*arch, "\n"); */

    while ( !C_Vacia( rev->cambios ) )
    {
        C_Sacar( &(rev->cambios), &cambios);
        if ( cambios.tipo == TAV_INSE )
            /* Se inserta linea (I@) */
            fprintf(*arch, "I@%d %s", cambios.pos, cambios.texto);
        else
            /* Se elimina linea (E@) */
            fprintf(*arch, "E@%d %s", cambios.pos, cambios.texto);

        free(cambios.texto);
    }

    fclose(*arch);

    return OK;
}


int guardarVersionN( TAV *tav, int version)
{   size_t verNombreLong, rutaLong;
    char *verNombre, verExt[3];
    int verExtLong;
    FILE *arch;
    revision_t rev;

    rutaLong = strlen(tav->ruta)+CSTR_FIN;
    verNombreLong = rutaLong + EXT_REV_LONG + CSTR_FIN;
    verNombre = (char*) malloc ( verNombreLong * sizeof(char) );
    if ( verNombre == NULL ) return ERR_MALLOC;

    strncpy(verNombre, tav->ruta, rutaLong);
    verExtLong = sprintf(verExt, ".%d", version);
    strncat(verNombre, verExt, verExtLong);

    arch = fopen(verNombre, "w+");
    free(verNombre);
    if ( arch == NULL ) return ERR_ABRIR_ARCHIVO;

    encontrarRevision(tav, version, &rev);
    escribirRevision(&rev, &arch);
    L_Modificar_Cte(tav->revisiones, &rev);

    return OK;
}


int cargarInfo(info_revision_t* info, FILE** arch)
{
    int ver;
    size_t lineaLong;
    char linea[CSTR_LONG], aux[CSTR_LONG];

    /* fscanf(*arch, "%*s %d", &ver); */
    fgets(linea, CSTR_LONG, *arch);
    sscanf(linea, "%*s %d", &ver);

    info->num = ver; /* Guardo la versión en info  */

    /* fscanf(*arch, "%[\n]", linea);*/
    fgets(linea, CSTR_LONG, *arch);
    lineaLong = strlen(linea)+CSTR_FIN;
    info->fecha = (char*) malloc(lineaLong * sizeof(char));
    strncpy(info->fecha, linea, lineaLong); /* Guardo la fecha en info  */

    /* fscanf(*arch, "%[^\n]", linea); */
    fgets(linea, CSTR_LONG, *arch);
    sscanf(linea, "%*s %[^\n]s", aux);
    lineaLong = strlen(aux) + 1;
    info->comentario = (char*) malloc(lineaLong * sizeof(char));
    strncpy(info->comentario, aux, lineaLong); /* Guardo el comentario en info  */

    return OK;
}


int agregarInfo(info_revision_t *info, char *coment, int version)
{   char fecha[FECHA_LONG];
    size_t longStr;

    gettime(fecha, &longStr);
    info->fecha = (char*) malloc( longStr * sizeof(char) );
    if ( info->fecha == NULL ) return ERR_MALLOC;
    strncpy( info->fecha, fecha, longStr );

    if ( coment != NULL)
    {
        longStr = strlen(coment)+CSTR_FIN;
        info->comentario = (char*) malloc( longStr * sizeof(char) );
        if ( info->comentario == NULL ) return ERR_MALLOC;
        strncpy( info->comentario, coment, longStr );
    }
    else
    {
        info->comentario = (char*) malloc( sizeof(char) );
        if ( info->comentario == NULL ) return ERR_MALLOC;
        strncpy( info->comentario, COMENT_VACIO, COMENT_VACIO_LONG);
    }

    info->num = version;

    return OK;
}


int cargarCambios(TCola *cambios, FILE **arch )
{   cambio_t cambio;
    char linea[CSTR_LONG], aux[CSTR_LONG];
    char *tipoCambio;
    int renglon, lineaLong;


    /* fscanf(*arch, "%[^\n]s", linea); */  /* descarto la linea en blanco */
    /* fgets(linea, CSTR_LONG, *arch); */  /* descarto la linea en blanco */

    /* fscanf(*arch, "%[^\n]s", linea); */
    fgets(linea, CSTR_LONG, *arch);
    for( renglon = MINIMO; NOT feof(*arch); renglon++ )
    {
        sscanf(linea, "%*s %[^\n]s", aux);      /* saco el encabezado @ */
        lineaLong = strlen(aux)+CSTR_FIN;
        cambio.texto = (char*) malloc( lineaLong * sizeof(char) );
        if ( cambio.texto == NULL ) return ERR_MALLOC;

        strncpy(cambio.texto, aux, lineaLong);        /* Guardo la modificacion en cambio */

        sscanf(linea, "%*c %*c %d", &renglon);
        cambio.pos = renglon;        /* Guardo el renglón en cambio */

        /* TODO revisar esto!! */
        tipoCambio = strstr(linea, INSE); /* linea contiene @I (INSE) */
        if ( tipoCambio != NULL )
            cambio.tipo = TAV_INSE;        /* Guardo el tipo del cambio */
        else
        {
            tipoCambio = strstr(linea, ELIM); /* linea contiene @E (ELIM) */
            if ( tipoCambio != NULL )
                cambio.tipo = TAV_ELIM;        /* Guardo el tipo del cambio */
            else
                return ERROR;
        }

        C_Agregar(cambios, &cambio);
        /* fscanf(*arch, "%[^\n]s", linea); */
        fgets(linea, CSTR_LONG, *arch);
    }

    return OK;
}


int guardarCambios(TCola *duplas, TCola *cambios, FILE **archActualVersion, FILE **archProxVersion)
{   int i = MINIMO, j = MINIMO, lineaLong;
    char linea[CSTR_LONG] = {'\0'};
    tDupla coinciden;
    cambio_t cambio;

    rewind(*archActualVersion);
    rewind(*archProxVersion);

    while ( NOT C_Vacia(*duplas) )
    {
        C_Sacar(duplas, coinciden);

        while ( j < coinciden[ARCH_UNO] )
        {
           /* fscanf(*archActualVersion, "%[^\n]s", linea); */
           fgets(linea, CSTR_LONG, *archActualVersion);
           cambio.pos = j;
           lineaLong = strlen(linea)+CSTR_FIN;
           cambio.texto = (char*) malloc( lineaLong * sizeof(char) );
           strncpy( cambio.texto, linea, lineaLong );
           cambio.tipo = TAV_ELIM;
           C_Agregar(cambios, &cambio);
           j++;
        }

        while ( i < coinciden[ARCH_DOS] )
        {
            /* fscanf(*archProxVersion, "%[^\n]s", linea); */
            fgets(linea, CSTR_LONG, *archProxVersion);
            cambio.pos = i;
            lineaLong = strlen(linea)+CSTR_FIN;
            cambio.texto = (char*) malloc( lineaLong * sizeof(char) );
            strncpy( cambio.texto, linea, lineaLong );
            cambio.tipo = TAV_INSE;
            C_Agregar(cambios, &cambio);
            i++;
        }

        /* fscanf(*archActualVersion, "%*[\n]"); */
        /* fscanf(*archProxVersion, "%*[\n]"); */
        fgets(linea, CSTR_LONG, *archProxVersion);
        fgets(linea, CSTR_LONG, *archActualVersion);
        i++; j++;

    }

    /* while ( NOT feof(*archActualVersion) ) */
    while ( fgets(linea, CSTR_LONG, *archActualVersion) != NULL )
    {
        /* fscanf(*archActualVersion, "%[^\n]s", linea); */
        /* fgets(linea, CSTR_LONG, *archActualVersion); */
        cambio.pos = j;
        lineaLong = strlen(linea)+CSTR_FIN;
        cambio.texto = (char*) malloc( lineaLong * sizeof(char) );
        strncpy( cambio.texto, linea, lineaLong );
        cambio.tipo = TAV_ELIM;
        C_Agregar(cambios, &cambio);
        j++;
    }

    /* while ( NOT feof(*archProxVersion) ) */
    while ( fgets(linea, CSTR_LONG, *archProxVersion) != NULL )
    {
        /* fscanf(*archProxVersion, "%[^\n]s %*s", linea); */
        /* fgets(linea, CSTR_LONG, *archProxVersion); */
        cambio.pos = i;
        lineaLong = strlen(linea)+CSTR_FIN;
        cambio.texto = (char*) malloc( lineaLong * sizeof(char) );
        strncpy( cambio.texto, linea, lineaLong );
        cambio.tipo = TAV_INSE;
        C_Agregar(cambios, &cambio);
        i++;
    }

    return OK;
}


int cargarTAV(TAV *tav, FILE **archVerN )
{   int resultado;
    revision_t revision;

    /* L_Crear( &(tav->revisiones), sizeof(revision_t) ); */
    C_Crear( &revision.cambios, sizeof(cambio_t) );

    resultado = cargarInfo(&revision.info, archVerN);
    if ( resultado != OK ) return resultado;

    resultado = cargarCambios(&revision.cambios, archVerN);
    if ( resultado != OK ) return resultado;

    L_Insertar_Cte( &(tav->revisiones), L_Siguiente, &revision);

    return OK;
}


int encontrarCoincidencias(TCola* duplas, FILE **archAnterior, FILE **archNuevo)
{   tDupla coinciden;

    char lineaArch1[CSTR_LONG], lineaArch2[CSTR_LONG];
    int renglonArch1 = MINIMO, renglonArch2 = MINIMO;

    C_Crear(duplas, sizeof(tDupla) );

    /* fscanf(*archAnterior, "%[^\n]s", lineaArch1); */
    fgets(lineaArch1, CSTR_LONG, *archAnterior);
    for ( renglonArch1 = MINIMO; NOT feof(*archAnterior); renglonArch1++)
    {

        /* fscanf(*archNuevo, "%[^\n]s", lineaArch2); */
        fgets(lineaArch2, CSTR_LONG, *archNuevo);
        for ( renglonArch2 = MINIMO; NOT feof(*archNuevo); renglonArch2++)
        {
            if ( strcmp(lineaArch1, lineaArch2) == EQUAL )
            {
                coinciden[ARCH_UNO] = renglonArch1;
                coinciden[ARCH_DOS] = renglonArch2;
                C_Agregar(duplas, &coinciden);
                /* k = renglonArch2; */
            }

            /* fscanf(*archNuevo, "%[^\n]s", lineaArch2); */
            fgets(lineaArch2, CSTR_LONG, *archNuevo);
        }
        rewind(*archNuevo);

        /* fscanf(*archAnterior, "%[^\n]s", lineaArch1); */
        fgets(lineaArch1, CSTR_LONG, *archAnterior);
    }

    return OK;
}




int TAV_Abrir ( TAV* tav, const char* ruta, modo_uso_t modo)
{   int result;
    int version, proxVersion;
    FILE *archVer;

    archVer = fopen(ruta, "r+");
    if ( archVer == NULL )
        return ERROR;
    else
        fclose(archVer);

    tav->ruta = (char*) malloc( ( strlen(ruta)+CSTR_FIN ) * sizeof(char) ); /* Copio la ruta en el tav */
    strncpy(tav->ruta, ruta, strlen(ruta)+CSTR_FIN );

    result = consultarTAV(tav, modo, &proxVersion); /*  */
    if ( result != OK ) return ERROR;

    result = verificarCURRENT(tav, modo);
    if ( result != OK ) return ERROR;

    L_Crear( &(tav->revisiones), sizeof(revision_t) );
    if ( modo == TAV_CREAR )
    {
        return ARCH_VERSIONADO;
    }
    else /* modo == TAV_USAR */
    {
        for( version = MINIMO; version < proxVersion; version++)
        {
            abrirVersionN(tav, version, &archVer);
            if ( archVer == NULL ) return ERROR;
            cargarTAV(tav, &archVer);
            fclose(archVer);
        }
    }

    return OK;
}


int TAV_Liberar ( TAV *tav)
{   /**  Libera la memoria del tav, y además borra todos los archivos
     *   que se crearon para mantener el versionado del archivo
     **/

    int version, i, result;
    size_t verNombreLong, rutaLong;
    char* verNombre;
    char verExt[3];
    int verExtLong;

    consultarTAV(tav, TAV_USAR, &version);
    for ( i = MINIMO; i < version; i++ )
    {
        rutaLong = strlen(tav->ruta)+CSTR_FIN;
        verNombreLong = rutaLong + EXT_REV_LONG + CSTR_FIN;
        verNombre = (char*) malloc ( verNombreLong * sizeof(char) );
        if ( verNombre == NULL ) return ERROR; /* ERR_MALLOC; */

        strncpy(verNombre, tav->ruta, rutaLong);
        verExtLong = sprintf(verExt, ".%d", i);
        strncat(verNombre, verExt, verExtLong);

        result = remove(verNombre);
        free(verNombre);
        if ( result != OK ) return ERROR;
    }

    result = borrarCURRENT(tav);
    if ( result != OK ) return ERROR;

    result = borrarTAV(tav);
    if ( result != OK ) return ERROR;

    result = TAV_Cerrar(tav);
    if ( result != OK ) return ERROR;


    return OK;
}


int TAV_Cerrar ( TAV *tav)
{/* (Solamente) Libera la memoria que se usó para el tav */
    /* Comprobar donde puede fallar y devolver ERROR */

    revision_t revision;
    cambio_t cambio;

    L_Mover_Cte( &(tav->revisiones), L_Primero );
    while ( L_Vacia(tav->revisiones) == FALSE )
    {
        L_Elem_Cte(tav->revisiones, &revision);
        while ( !C_Vacia(revision.cambios)  ) /* TODO esto suele romper cuando está vacía ¿¿XQ?? */
        {
            C_Sacar( &(revision.cambios), &cambio);
            free(cambio.texto);
        }
        free(revision.info.comentario);
        free(revision.info.fecha);
        L_Borrar_Cte( &(tav->revisiones) );
    }

    free(tav->ruta);

    return OK;
}


int TAV_GetInfoRevision ( TAV* tav, int rev, info_revision_t *info )
{   int result, ver;
    FILE *arch;

    if ( L_Vacia(tav->revisiones) == TRUE ) return ERROR2;

    consultarTAV(tav, TAV_USAR, &ver);
    if ( rev >= ver ) return ERROR;

    abrirVersionN(tav, rev, &arch);
    if ( arch == NULL ) return ERROR2;

    result = cargarInfo(info, &arch);
    if ( result != OK ) return ERROR2;

    return OK;
}


int TAV_GetListaRevisiones ( TAV* tav, TListaSimple *info )
{   revision_t dato;

    if ( L_Vacia(*info) == FALSE ) return ERROR;
    if ( L_Vacia(tav->revisiones) == TRUE ) return ERROR;

    L_Mover_Cte( &(tav->revisiones), L_Primero);

    do
    {
        L_Elem_Cte(tav->revisiones, &dato);
        L_Insertar_Cte(info, L_Siguiente, &(dato.info));

    }while ( L_Mover_Cte( &(tav->revisiones), L_Siguiente) == TRUE );

    L_Mover_Cte(info, L_Primero);

    return OK;
}


int TAV_Actualizar(TAV *tav, char *comentario)
{   FILE *archVerActual, *archVerProx;
    int ver, result;
    TCola cambios, duplas;
    info_revision_t info;

    C_Crear( &cambios, sizeof(cambio_t) );

    consultarTAV(tav, TAV_USAR, &ver);
    result = abrirCURRENT(tav, &archVerActual);
    if ( result != OK ) return ERROR;
    archVerProx = fopen(tav->ruta, "r+");

    encontrarCoincidencias(&duplas, &archVerActual, &archVerProx);
    guardarCambios(&duplas, &cambios, &archVerActual, &archVerProx);
    fclose(archVerActual);
    fclose(archVerProx);

    /* if ( ver == INICIO ) ver++; */  /* porque cuando tav contiene 0, la prox versión en realidad es 1 */

    agregarInfo(&info, comentario, ver);
    actualizarTAV(tav, info, &cambios);

    guardarVersionN(tav, ver);
    actualizarCURRENT(tav);
    actualizarArchTAV(tav);

    return OK;
}


int TAV_GetTcola(TAV *tav,int rev,TCola *CambiosAUsar)

{/**no va a probar casi nada(nada), simplemente hace lo que tiene que hacer porque cuando la llamo ya probe todo*/



    revision_t Elemento;



    L_Mover_Cte(&tav->revisiones,L_Primero);

    L_Elem_Cte(tav->revisiones, &Elemento);



        if (Elemento.info.num==rev) {

        memcpy(CambiosAUsar,&Elemento.cambios,sizeof(Elemento.cambios));

        return 0;

        }

    while (L_Mover_Cte(&tav->revisiones,L_Siguiente)){



         L_Elem_Cte(tav->revisiones, &Elemento);





        if (Elemento.info.num==rev) {

        memcpy(CambiosAUsar,&Elemento.cambios,sizeof(Elemento.cambios));

        return 0;



        }

    }

    return -1;/*no existia la revisiosn numero rev*/

}





int TAV_Deshacer ( TAV* tav, int rev, char* comentario )

{

FILE *archVerActual, *archVerProx;
int result;
TCola duplas;
info_revision_t info;

FILE* archivoCurrent=NULL;
FILE* miArchivoCurrent=NULL;
FILE* nuevaVersion=NULL;

char* nombredearchivo=NULL;

int i=0,n=0, filadelarchivo=1, current=0;

TCola CambiosAUsar;

cambio_t UnCambio;

char linea[CSTR_LONG];



if (rev<0) return NO_REVISION;


/**abro el .tav para saber porque numero de revision va*/

consultarTAV(tav, TAV_USAR, &n);


if(rev>n-2) return NO_REVISION; /*n-1 es la actual asi q minimo tiene que ser -2*/



/** A esta altura me asegure que la revision buscada existe.*/


/**procedo a abrir el archivo actual y el archivo donde voy a regenerar la version anterior.*/

nombredearchivo = (char*) malloc ( strlen(tav->ruta)+1+ EXT_CUR_LONG);

if ( nombredearchivo == NULL ) return ERR_MALLOC;

strncpy(nombredearchivo, tav->ruta, strlen(tav->ruta)+1);

strncat(nombredearchivo, EXTENSION_CURRENT, EXT_CUR_LONG);

archivoCurrent=fopen(nombredearchivo,"r+");

free(nombredearchivo);

/**sin embargo no puedo usar este current porque por como esta hecho mi algoritmo se terminaria modificando. y lo necesito

intacto para compararlo con la version recuperada para hacer la nueva cola de cambios entre el current y la "nueva version".

Asi que lo copiamos todo en mi current :D */




miArchivoCurrent=fopen("aSerEliminado.txt","w+");
if ( miArchivoCurrent == NULL ) return ERR_ABRIR_ARCHIVO;

while ( fgets(linea, CSTR_LONG, archivoCurrent ) != NULL )
{
    fprintf(miArchivoCurrent, "%s", linea);

}

fclose(archivoCurrent);
fclose(miArchivoCurrent);
current=n-1;

while(current!=rev){

nuevaVersion=fopen("nuevaVersion.txt","w+");
miArchivoCurrent=fopen("aSerEliminado.txt","r+");

TAV_GetTcola(tav,current,&CambiosAUsar);
filadelarchivo=1;
/**PERFEECTO! tengo en cambiosAUsar la lista de cambios para volver a la version ccurrent-1.

tambien ya abri el archivo nuevaVersion que es donde voy a guardar este retrooceso de una version.

Tengo los int FiladeArchivo y FilaDeCambio inicializadas en 1 para hacer el algoritmos.

vamos con eso :D*/





/**

Para cada línea del archivo de cambios

Si el tipo es I

Copiar la versión guardada desde la última posición leída hasta la línea anterior a la indicada en el cambio.

Descartar la siguiente línea de la versión guardada.

Si el tipo es E

Copiar la versión guardada desde la última posición leída hasta haber escrito la línea anterior a la indicada en el cambio.

Escribir el contenido del cambio.

*/





while(C_Vacia(CambiosAUsar)==FALSE)

{

 C_Sacar(&CambiosAUsar, &UnCambio);


 for (i=filadelarchivo;i<UnCambio.pos;i++,filadelarchivo++){

         fgets(linea, CSTR_LONG, miArchivoCurrent);
         fprintf(nuevaVersion, "%s", linea);

 }




 if (UnCambio.tipo==TAV_INSE){

     fgets(linea, CSTR_LONG, miArchivoCurrent);/**descarto esta linea.*/

    filadelarchivo++;

}

 else if (UnCambio.tipo==TAV_ELIM){
    fprintf(nuevaVersion, "%s\n", UnCambio.texto);

}

}



/**ahora terminamos de copiar lo que queda en el final del archivo current al archivo nueva version;D */



while ( fgets(linea, CSTR_LONG, miArchivoCurrent) != NULL ){

    fprintf(nuevaVersion, "%s", linea);

}





current--;

if (current!=rev)/**osea, si aun tengo que deshacer otro rollback*/{

        fclose(miArchivoCurrent);

        fclose(nuevaVersion);

        remove("aSerEliminado.txt");

        rename("nuevaVersion.txt","aSerEliminado.txt");/**de este modo cuando vuelva a empezar el ciclo while del principio va a tomar como el current a la version que recupere recien :D */

}

else

{
        fclose(miArchivoCurrent);

        fclose(nuevaVersion);

        remove("aSerEliminado.txt");

        remove(tav->ruta);

        rename("nuevaVersion.txt",tav->ruta);

}

}


/**soy una genia :D*/

 C_Vaciar(&CambiosAUsar);


 result = abrirCURRENT(tav, &archVerActual);
 if ( result != OK ) return ERROR;
 archVerProx = fopen(tav->ruta, "r+");

 encontrarCoincidencias(&duplas, &archVerActual, &archVerProx);
 guardarCambios(&duplas, &CambiosAUsar, &archVerActual, &archVerProx);
 fclose(archVerActual);
 fclose(archVerProx);

 agregarInfo(&info, comentario, n);
 actualizarTAV(tav, info, &CambiosAUsar);

 guardarVersionN(tav, n);
 actualizarCURRENT(tav);
 actualizarArchTAV(tav);



return OK;

}
